package im.zhaojun.zfile.module.storage_search.service.impl;

import im.zhaojun.zfile.core.exception.file.InvalidStorageSourceException;
import im.zhaojun.zfile.module.storage.context.StorageSourceContext;
import im.zhaojun.zfile.module.storage.model.enums.FileTypeEnum;
import im.zhaojun.zfile.module.storage.model.result.FileItemResult;
import im.zhaojun.zfile.module.storage.service.StorageSourceService;
import im.zhaojun.zfile.module.storage.service.base.AbstractBaseFileService;
import im.zhaojun.zfile.module.storage_search.model.enums.FileSearchModeEnum;
import im.zhaojun.zfile.module.storage_search.model.request.FileSearchRequest;
import im.zhaojun.zfile.module.storage_search.service.FileSearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: zw
 * @date: 2024/7/30 17:39
 */
@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Slf4j
public class FileSearchServiceImpl implements FileSearchService {

    private List<FileItemResult> searchResultList = new ArrayList<>();

    @Resource
    private StorageSourceContext storageSourceContext;

    @Resource
    private StorageSourceService storageSourceService;

    @Override
    public List<FileItemResult> search(FileSearchRequest fileSearchRequest) throws Exception {
        String storageKey = fileSearchRequest.getStorageKey();
        Integer storageId = storageSourceService.findIdByKey(storageKey);
        if (storageId == null) {
            throw new InvalidStorageSourceException("通过存储源 key 未找到存储源, key: " + storageKey);
        }

        // 获取文件服务对象
        AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageId(storageId);

        String searchMode = fileSearchRequest.getSearchMode();
        String searchKeyword = fileSearchRequest.getSearchKeyword();
        if (searchMode.equals(FileSearchModeEnum.SEARCH_CURRENT_FOLDER.getValue())){
            //查询当前目录下
            searchResultList = fileService.fileList(fileSearchRequest.getPath()).stream()
                    .filter((f) -> f.getName().contains(searchKeyword))
                    .collect(Collectors.toList());
        }
        else if (searchMode.equals(FileSearchModeEnum.SEARCH_CURRENT_AND_CHILD.getValue())){
            //查询当前目录和子目录
            Deque<String> directories = new ArrayDeque<>();
            directories.add(fileSearchRequest.getPath());
            searchCycle(fileService, directories, searchKeyword, searchResultList);
        }
        else if (searchMode.equals(FileSearchModeEnum.SEARCH_ALL.getValue())){
            //查询当前数据源下全部
            //直接从根目录开始
            Deque<String> directories = new ArrayDeque<>();
            directories.add("/");
            searchCycle(fileService, directories, searchKeyword, searchResultList);
        }

        return searchResultList;
    }


    private void searchCycle(AbstractBaseFileService<?> fileService, Deque<String> directories, String searchKeyword, List<FileItemResult> results) throws Exception {
        if (StringUtils.isBlank(searchKeyword)) return;

        while (!directories.isEmpty()) {
            String currentDirectory = directories.pop();
            List<FileItemResult> fileItemList = fileService.fileList(currentDirectory);

            if (fileItemList != null) {
                for (FileItemResult fileItem : fileItemList) {
                    if (fileItem.getName().contains(searchKeyword)){
                        results.add(fileItem);
                    }
                    if (fileItem.getType() == FileTypeEnum.FOLDER) {
                        directories.add(fileItem.getPath() + "/" + fileItem.getName());
                    }
                }
            }
        }
    }
}
